#include <string.h>
#include <iostream>
using std::cout;
using std::endl;

class Computer
{
public:
    Computer(const char * brand,double price)
    : _brand(new char[strlen(brand) + 1]())
    , _price(price)
    {
        cout << "Computer(const char*,double)" << endl;
        strcpy(_brand,brand);
    }

    Computer(const Computer & rhs)
    : _brand(new char[strlen(rhs._brand) + 1]())
    , _price(rhs._price)
    {
        strcpy(_brand,rhs._brand);
        cout << "拷贝构造函数" << endl;
    }

    Computer & operator=(const Computer & rhs){
        cout << "赋值运算符函数" << endl;
        if(this != &rhs){
            delete [] _brand;
            _brand = new char[strlen(rhs._brand) + 1]();
            strcpy(_brand,rhs._brand);
            _price = rhs._price;
        }
        return *this;
    }

    ~Computer(){
        cout << "~Computer()" << endl;
        if(_brand){
            delete [] _brand;
            _brand = nullptr;
        }
    }

    void print(){
        cout << "brand:" << _brand << endl;
        cout << "price:" << _price << endl;
    }
private:
    char * _brand;
    double _price;
};

template <class T>
class RAII
{
public:
    //1.构造函数托管资源
    RAII(T * data)
    : _data(data)
    {
        cout << "RAII(T*)" << endl;
    }

    //2.析构函数释放资源
    ~RAII(){
        cout << "~RAII" << endl;
        if(_data){
            delete _data;
            _data = nullptr;
        }
    }

    //3.不允许复制或赋值
    RAII(const RAII & rhs) = delete;
    RAII & operator=(const RAII & rhs) = delete;

    //4.提供若干访问资源的方式
    T * operator->(){
        return _data;
    }

    T & operator*(){
        return *_data;
    }

    T * get() const{
        return _data;
    }

    void reset(T * data){
        if(_data){
            delete _data;
            _data = nullptr;
        }
        _data = data;
    }
private:
    T * _data;
};

void test0(){
    //不推荐
    /* Computer * p = new Computer("apple",20000); */
    /* RAII<Computer> raii2(p); */
    /* delete p; */
    

    //推荐
    RAII<Computer> raii(new Computer("lenovo",7000));
    raii->print();
    (*raii).print();
    cout << raii.get() << endl;
    
    cout << endl;
    raii.reset(new Computer("Asus",6000));
    raii->print();
    (*raii).print();
    cout << raii.get() << endl;
}

int main(void){
    test0();
    return 0;
}



